from time import strftime
from google.appengine.ext import db
from google.appengine.ext.db import GqlQuery

__author__="elad"
__date__ ="$Feb 26, 2009 11:26:19 PM$"

class LogMessage(db.Model):
	timestamp = db.DateTimeProperty(auto_now_add=True)
	logger_ip = db.StringProperty()
	app_name = db.StringProperty()
	logger_name = db.StringProperty()
	severity = db.IntegerProperty()
	message = db.StringProperty(multiline=True)
	stack_dump = db.TextProperty()
	dev_mode = db.BooleanProperty()
	
	Severities = ['TRACE', 'DEBUG', 'INFO', 'WARN', 'ERROR', 'FATAL']
	
	def severity_name(self):
		if ((self.severity < 0) or (self.severity > len(self.Severities) - 1)):
			return ''
		return self.Severities[self.severity]

	def rfc2282_time(self):
		return strftime("%a, %d %b %Y %H:%M:%S +0000", self.timestamp.timetuple())

	def break_logger_name(self):
		if len(self.logger_name) > 25:
			s = self.logger_name[0:25]
			i = 25
			while len(self.logger_name) > i:
				s += "\n%s" % self.logger_name[i:i+25]
				i += 25
			return s
		else:
			return self.logger_name

	def get_field(self, field_name, nchars=None):
		if field_name == 'logger_ip':
			s =  self.logger_ip
		elif field_name == 'app_name':
			s = self.app_name
		elif field_name == 'logger_name':
			s = self.logger_name
		elif field_name == 'message':
			s = self.message
		elif field_name == 'severity':
			s = self.severity_name()
		elif field_name == 'dev_mode':
			s = self.dev_mode
		else:
			s = ''
		if len(s) > 0 and nchars:
			return s[0:nchars]
		else:
			return s

	@staticmethod
	def get_query_from_filter(filter):
		conditions = filter.to_conditions()
		condition = "SELECT * FROM LogMessage "
		i = 0
		while i < len(conditions):
			if i > 0:
				condition += ' AND '
			else:
				condition += ' WHERE '
			condition += '%s:%d%s' % (conditions[i][0], i+1, conditions[i][2])
			i += 1
		condition += " ORDER BY timestamp DESC LIMIT 100"
		params = [c[1] for c in conditions]
		return GqlQuery(condition, *params)


class Filter(db.Model):
	""" A saved filter, that users can subscribe to and create alerts for """
	user = db.UserProperty()
	description = db.StringProperty()
	ts_min = db.DateTimeProperty()
	ts_max = db.DateTimeProperty()
	ts = db.StringProperty()
	logger_ip = db.StringProperty()
	app_name = db.StringProperty()
	logger_name = db.StringProperty()
	severity = db.IntegerProperty()
	dev_mode = db.BooleanProperty()

	def to_conditions(self):
		"""Return a list of conditions based on this filter, useful for building queries"""
		conditions = []
		if self.logger_ip:
			conditions.append(["logger_ip = ", self.logger_ip, ''])
		if self.ts_min:
			conditions.append(["timestamp >= ", self.ts_min, ''])
		if self.ts_max:
			conditions.append(["timestamp <= ", self.ts_max, ''])
		if self.app_name:
			conditions.append(["app_name = ", self.app_name, ''])
		if self.logger_name:
			conditions.append(["logger_name = ", self.logger_name, ''])
		if self.severity:
			conditions.append(["severity = ", self.severity, ''])
		if not self.dev_mode:
			conditions.append(["dev_mode = ", self.dev_mode, ''])
			
		return conditions
		
	def match(self, message):
		if (self.ts_min and message.timestamp < self.ts_min):
			return False
		if (self.ts_max and message.timestamp > self.ts_max):
			return False
		if (self.logger_ip and not (message.logger_ip.lower() == self.logger_ip.lower())):
			return False
		if (self.app_name and not (message.app_name.lower() == self.app_name.lower())):
			return False
		if (self.logger_name and not (message.logger_name.lower() == self.logger_name.lower())):
			return False
		if (self.severity and not (message.severity == self.severity)):
			return False
		if (self.dev_mode and not (message.dev_mode == self.dev_mode)):
			return False		
		return True

	def to_string(self):
		s = ''
		if self.logger_ip:
			s += '<b>ip</b>: %s ' % self.logger_ip
		if self.ts_min or self.ts_max:
			s += '<b>time</b>: %s - %s ' % (self.ts_min or '.', self.ts_max or '.')
		if self.app_name:
			s += '<b>app</b>: %s ' % self.app_name
		if self.logger_name:
			s += '<b>logger</b>: %s ' % self.logger_name
		if self.severity:
			s += '<b>severity</b>: %s ' % LogMessage.Severities[self.severity]
		if self.dev_mode:
			s += '<b>dev_mode</b>: %s ' % self.dev_mode			
		return s

class Alert(db.Model):
	user = db.UserProperty()
	filter = db.ReferenceProperty(Filter)
	url = db.LinkProperty()
	method = db.StringProperty()
	authentication = db.StringProperty()
	payload = db.TextProperty()
